home *** CD-ROM | disk | FTP | other *** search
/ JCSM Shareware Collection 1993 November / JCSM Shareware Collection - 1993-11.iso / cl720 / sst115j.lzh / SSTMNU.C < prev    next >
C/C++ Source or Header  |  1992-07-17  |  11KB  |  371 lines

  1. /* ------------------------------------------------------------------------ */
  2. /*                                sstmenu.c                                 */
  3. /*                   pull-down menu interface routines                      */
  4. /*                                                                          */
  5. /*      CopyRight (C) 1991,1992  Steven Lutrov.   All rights reserved.      */
  6. /* ------------------------------------------------------------------------ */
  7. #include <stdio.h>
  8. #include <conio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <ctype.h>
  12. #include <dos.h>
  13.  
  14. #include "sstvid.h"
  15. #include "sstkey.h"
  16. #include "sstwin.h"
  17. #include "sstmnu.h"
  18.  
  19. typedef struct  {
  20.      int  x;
  21.      int  xx;
  22. } itemrec;
  23.  
  24. typedef struct _mstyle {
  25.     char    *title;                      /* title string */
  26.     int     tjust;                       /* title justification */
  27.     int     border;                      /* border type  */
  28.     int     colour[4];                   /* colours for window  */
  29.     int     hspace;                      /* spaces between horiz items  */
  30.     int     lspace;                      /* left margin */
  31.     int     rspace;                      /* right marigin  */
  32.     int     hfull;                       /* use full horiz width  */
  33. } MSTYLE;
  34.  
  35.  
  36. static MSTYLE ms = {            /* set default to monochrome attributes */
  37.    "", JUST_C, BRD_SINGLE,
  38.        { CLR(BLACK,     LIGHTGRAY, DIM),
  39.      CLR(BLACK,     LIGHTGRAY, DIM),
  40.      CLR(LIGHTGRAY, BLACK,     BRIGHT),
  41.      CLR(BLACK,     LIGHTGRAY, DIM)
  42.        },
  43.    2,   /* spaces */
  44.    1,   /* left margin */
  45.    1,   /* right margin */
  46.    0    /* full screen width */
  47.    };
  48.  
  49. #define MWIN_BORDER       (ms.colour[WIN_BORDER])
  50. #define MWIN_TITLEC       (ms.colour[WIN_TITLE])
  51. #define MWIN_ACCENT        (ms.colour[WIN_ACCENT])
  52. #define MWIN_FACE          (ms.colour[WIN_FACE])
  53. #define MCOLOUR            (ms.colour)
  54. #define MAXITEMS           16             /* maximum horiz menu items */
  55.  
  56. #define HKTAG    '~'
  57.  
  58. int msave = 1;
  59.  
  60. /* ------------------------------------------------------------------------ */
  61. /*                       local function prototypes                          */
  62. /* ------------------------------------------------------------------------ */
  63.  
  64. WINDOW *openmenu        (MENU *mn, int hsel);
  65. static int  gethmenu    (MENU *mn, WINDOW *hmenu, int hsel);
  66. static int  getvmn      (MENU *mn, WINDOW *hmenu, int *, int );
  67. static int  haccent     (MENU *mn, WINDOW *hmenu, int hsel, int vsel);
  68. static void dimension   (char *sl[], int *ht, int *wd);
  69. static void light       (MENU *mn, WINDOW *hmenu, int hsel, int d);
  70. static int  getwidth    (MENU *mn);
  71. static int  getvertpos  (char **sl, int h);
  72. static void putitems    (WINDOW *wnd, MENU *mn);
  73.  
  74.  
  75. /* ------------------------------------------------------------------------ */
  76. /*                             local variables                              */
  77. /* ------------------------------------------------------------------------ */
  78.  
  79. static itemrec irec[MAXITEMS];   /* item records */
  80. static int w;                    /* horizontal window width */
  81. static int hc;                   /* horizontal item count */
  82.  
  83.  
  84. /* ------------------------------------------------------------------------ */
  85. /*                      display & process a menu                            */
  86. /* ------------------------------------------------------------------------ */
  87. int Mselect(MENU *mn, int h)
  88. {
  89.   WINDOW *openmenu();
  90.   WINDOW *hmenu;
  91.   int hsel = 1, vsel;
  92.  
  93.  
  94.   vpushcur();
  95.   vhidecur();
  96.   if ((w = getwidth(mn)) > SCREENWIDTH)
  97.     return (-1);
  98.   w = ((ms.hfull) ? SCREENWIDTH : w);
  99.   if ((hmenu = openmenu(mn, hsel)) == NULL)
  100.        return (0);
  101.   while ( (hsel = gethmenu(mn, hmenu, hsel)) != 0)    {
  102.     vsel = 1;
  103.     while ( (vsel = getvmn(mn, hmenu, &hsel, vsel)) !=0) {
  104.         if(! h)
  105.             vpushscreen();
  106.         Wdelete(hmenu);
  107.         if(! h)
  108.             vpopscreen();
  109.         (*(mn+hsel-1)->func [vsel-1])(hsel, vsel);
  110.         if ((hmenu = openmenu(mn, hsel)) == NULL)
  111.             return (0);
  112.     }
  113.   }
  114.   Wdelete(hmenu);
  115.   vpopcur();
  116.   return (1);
  117. }
  118.  
  119. /* ------------------------------------------------------------------------ */
  120. /*                          open a horizontal menu                          */
  121. /* ------------------------------------------------------------------------ */
  122. static WINDOW *openmenu(MENU *mn, int hsel)
  123. {
  124.      WINDOW *wnd;
  125.  
  126.      vhidecur();
  127.      if ( (wnd = Westablish(0, 0, 3, w)) == NULL)
  128.        return (NULL);
  129.      Wsettitle(wnd, ms.title,ms.tjust);
  130.      WBORDER = MWIN_BORDER;
  131.      WTITLEC = MWIN_TITLEC;
  132.      WACCENT = MWIN_ACCENT;
  133.      WFACE = MWIN_FACE;
  134.      Wsetborder(wnd, ms.border);
  135.      Wshow(wnd);
  136.      putitems(wnd,mn);
  137.      light(mn, wnd, hsel, 1);
  138.      return wnd;
  139. }
  140.  
  141. /* ------------------------------------------------------------------------ */
  142. /*                        get a horizontal selection                        */
  143. /* ------------------------------------------------------------------------ */
  144. static int gethmenu(MENU *mn, WINDOW *hmenu, int hsel)
  145. {
  146.     int c;
  147.  
  148.     light(mn, hmenu, hsel, 1);
  149.     while (1) {
  150.       if (kkeyhit()) {
  151.       switch (c = kgetch())    {
  152.           case RIGHT:
  153.           case LEFT :  hsel = haccent(mn, hmenu, hsel, c);
  154.                  break;
  155.           case ESC  :  return 0;
  156.           case ENTER:  return hsel;
  157.           default:       break;
  158.           }
  159.        }
  160.       } /* while */
  161. }
  162.  
  163. /* ------------------------------------------------------------------------ */
  164. /*                        pop down a vertical menu                          */
  165. /* ------------------------------------------------------------------------ */
  166. static int getvmn(MENU *mn,WINDOW *hmenu,int *hsel,int vsel)
  167. {
  168.     WINDOW *wnd;
  169.     int ht, wd,x;
  170.     char **mp;
  171.  
  172.     while (1)    {
  173.     dimension((mn+*hsel-1)->mselcs, &ht, &wd);
  174.     x = getvertpos((mn+*hsel-1)->mselcs,*hsel-1);
  175.     wnd = Westablish(x, 2, ht, wd);
  176.     WBORDER = MWIN_BORDER;
  177.     WACCENT = MWIN_ACCENT;
  178.     WFACE = MWIN_FACE;
  179.     Wsetborder(wnd, ms.border+4);
  180.     Wshow(wnd);
  181.     mp = (mn+*hsel-1)->mselcs;
  182.     while(*mp)
  183.         Wprintf(wnd, "\n%s", *mp++);
  184.     vsel = Wgetsel(wnd, vsel, "");
  185.     Wdelete(wnd);
  186.     if (vsel == RIGHT || vsel == LEFT)    {
  187.         *hsel = haccent(mn, hmenu, *hsel, vsel);
  188.         vsel = 1;
  189.     }
  190.     else
  191.         return vsel;
  192.     }
  193. }
  194.  
  195. /* ------------------------------------------------------------------------ */
  196. /*                               set colours                                */
  197. /* ------------------------------------------------------------------------ */
  198. void Msetcolour(int area,int bg,int fg,int inten)
  199. {
  200.     if (ISMONO())    {
  201.     if (bg != WHITE && bg != BLACK)
  202.         return;
  203.     if (fg != WHITE && fg != BLACK)
  204.         return;
  205.      }
  206.     if (area == WIN_ALL)
  207.       while (area)
  208.      MCOLOUR [--area] = CLR(bg, fg, inten);
  209.       else
  210.      MCOLOUR [area] = CLR(bg, fg, inten);
  211. }
  212.  
  213.  
  214.  
  215. /* ------------------------------------------------------------------------ */
  216. /*                         set the window's border                          */
  217. /* ------------------------------------------------------------------------ */
  218. void Msetborder(int btype)
  219.  
  220. {
  221.    ms.border = btype;
  222. }
  223.  
  224. /* ------------------------------------------------------------------------ */
  225. /*                         set the window's border                          */
  226. /* ------------------------------------------------------------------------ */
  227. void Msetspace(int sp, int a)
  228.  
  229. {
  230.    if ((a) & SPC_LEFT)
  231.     ms.lspace = sp;
  232.    if ((a) & SPC_RIGHT)
  233.     ms.rspace = sp;
  234.    if ((a) & SPC_BETWEEN)
  235.     ms.hspace = sp;
  236. }
  237.  
  238. /* ------------------------------------------------------------------------ */
  239. /*                               set title                                  */
  240. /* ------------------------------------------------------------------------ */
  241. void Msettitle(char *title, int just)
  242.  
  243. {
  244.   ms.title = title;
  245.   ms.tjust = just;
  246. }
  247.  
  248. /* ------------------------------------------------------------------------ */
  249. /*                               set title                                  */
  250. /* ------------------------------------------------------------------------ */
  251. void Msetfullwidth(int f)
  252.  
  253. {
  254.   if (f)
  255.      ms.hfull = 1;
  256.       else
  257.        ms.hfull = 0;
  258. }
  259.  
  260. /* ------------------------------------------------------------------------ */
  261. /*                    display all the items on the vertical bar             */
  262. /* ------------------------------------------------------------------------ */
  263. static void putitems(WINDOW *wnd, MENU *mn)
  264.  
  265. {
  266.     int l;
  267.  
  268.     hc = 0;
  269.     for (l = 0 ; l < ms.lspace ; l++)
  270.             Wputch(wnd,' ');
  271.     while (mn->mname) {
  272.     Wprintf(wnd, "%s", mn->mname);
  273.     for (l = 0 ; l < ms.hspace ; l++)
  274.         Wputch(wnd,' ');
  275.     mn++;
  276.     hc++;
  277.      }
  278. }
  279.  
  280. /* ------------------------------------------------------------------------ */
  281. /*                 manage the horizontal menu selection accent              */
  282. /* ------------------------------------------------------------------------ */
  283. static int haccent(MENU *mn,WINDOW *hmenu,int hsel,int sel)
  284. {
  285.     switch (sel)    {
  286.     case RIGHT  : light(mn, hmenu, hsel, 0);
  287.               if ((mn+hsel)->mname)
  288.             hsel++;
  289.               else
  290.             hsel = 1;
  291.               light(mn, hmenu, hsel, 1);
  292.               break;
  293.     case LEFT   : light(mn, hmenu, hsel, 0);
  294.               if (hsel == 1)
  295.             while ((mn+hsel)->mname)
  296.                 hsel++;
  297.               else
  298.             --hsel;
  299.               light(mn, hmenu, hsel, 1);
  300.               break;
  301.     default    :  break;
  302.     }
  303.   return hsel;
  304. }
  305.  
  306. /* ------------------------------------------------------------------------ */
  307. /*                      compute a menu's height & width                     */
  308. /* ------------------------------------------------------------------------ */
  309. static void dimension(char *sl[], int *ht, int *wd)
  310. {
  311.     *ht = *wd = 0;
  312.     while (sl [*ht])    {
  313.         *wd = max(*wd, strlen(sl [*ht]));
  314.         (*ht)++;
  315.     }
  316.     *ht += 2;
  317.     *wd += 2;
  318. }
  319.  
  320. /* ------------------------------------------------------------------------ */
  321. /*                    accent a horizontal menu selection                    */
  322. /* ------------------------------------------------------------------------ */
  323. static void light(MENU *mn, WINDOW *hmenu, int hsel, int d)
  324. {
  325.     if (d)
  326.     Wrevvideo(hmenu);
  327.     Wcursor(hmenu, irec[hsel-1].x, 0);
  328.     Wprintf(hmenu, (mn+hsel-1)->mname);
  329.     Wresetvideo(hmenu);
  330. }
  331.  
  332. /* ------------------------------------------------------------------------ */
  333. /*       compute the window width required for the horizontal menu bar      */
  334. /* ------------------------------------------------------------------------ */
  335. static int getwidth(MENU *mn)
  336.  
  337. {
  338.    int c = 1,wd = 0;
  339.    const MENU *mptr = mn;
  340.  
  341.    irec[0].x = ms.lspace;
  342.    wd = ms.lspace;
  343.    while ((mptr)->mname) {
  344.       wd += strlen(mptr->mname) + ms.hspace;
  345.       irec[c].x = wd;
  346.       irec[(c++)-1].xx = strlen((mptr++)->mname);
  347.       }
  348.    wd -=  ms.hspace;
  349.    return (wd+ms.rspace+2);
  350. }
  351.  
  352. /* ------------------------------------------------------------------------ */
  353. /*       compute the window position  required for the vertical menu        */
  354. /* ------------------------------------------------------------------------ */
  355. static int getvertpos(char **sl, int h)
  356.  
  357. {
  358.   int x,l = 0;
  359.  
  360.   while (*sl)  {
  361.      l = max(l,strlen(*sl));
  362.      sl++;
  363.   }
  364.   if (h > (hc /2))
  365.      x = -3;
  366.      else
  367.        x = 2;
  368.   return  ( (irec[h].x+l < w)  ? irec[h].x : (w-l)) +x;
  369. }
  370.  
  371.